    // Copyright (C) 1953-2020 NUDT
// Verilog module name - tsn_packet_action
// Version: V3.2.0.20210722
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         forward based on the result of the lookup table
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module tsn_packet_action
(
        i_clk,
        i_rst_n,
        
        i_cyclestart   ,
        iv_inject_period,
              
        iv_md     ,  
        i_md_wr   ,  
                    
        iv_ram_rdata  ,
        o_ram_wr      ,
        ov_ram_waddr  ,
        ov_ram_wdata  ,
                    
        ov_md       ,
        o_md_wr     
);

// I/O
// clk & rst
input                  i_clk;                   //125Mhz
input                  i_rst_n;

input                  i_cyclestart;
input      [10:0]      iv_inject_period;
// pkt_bufid and pkt_type and outport from lookup_table
input      [299:0]     iv_md;
input                  i_md_wr;
// pkt_bufid and pkt_type to p0
(*MARK_DEBUG="true"*)output reg [299:0]     ov_md;
(*MARK_DEBUG="true"*)output reg             o_md_wr;
//read data from RAM
(*MARK_DEBUG="true"*)input      [73:0]      iv_ram_rdata;

(*MARK_DEBUG="true"*)output reg             o_ram_wr    ;
(*MARK_DEBUG="true"*)output reg [13:0]      ov_ram_waddr;
(*MARK_DEBUG="true"*)output reg [73:0]      ov_ram_wdata;

(*MARK_DEBUG="true"*)reg        [1023:0]    rv_first_packet_flag/*synthesis noprune*/;

reg                   debug_signal/*synthesis noprune*/;
//////////////////////////////////////////////////
//              forward                         //
//////////////////////////////////////////////////
always @(posedge i_clk or negedge i_rst_n) begin
    if(i_rst_n == 1'b0)begin
        ov_md                <= 300'h0;
        o_md_wr              <= 1'h0  ;
                             
        o_ram_wr             <= 1'b0 ;  
        ov_ram_waddr         <= 14'b0;
        ov_ram_wdata         <= 74'b0;
        
        debug_signal         <= 1'b0;
    end                              
    else begin
        if(i_md_wr == 1'b1)begin
            if(iv_md[111:96] != 16'h8100)begin//the pkt_bufid do not need lookup flowid table
                ov_md         <= iv_md;
                o_md_wr       <= i_md_wr;

                o_ram_wr      <= 1'b0 ; 
                ov_ram_waddr  <= 14'b0;
                ov_ram_wdata  <= 74'b0;
            end
            else begin//the pkt_bufid had lookup flowid table
                ov_md[299:200]         <= iv_md[299:200];
                ov_md[198:166]         <= {1'b0,iv_ram_rdata[63:32]};//outportBM.                
                ov_md[165:156]         <= iv_ram_rdata[9:0];//plan_slot.
                ov_md[155:115]         <= iv_md[155:115];
                ov_md[114:112]         <= iv_ram_rdata[31:29];//priority.
                ov_md[111:0]           <= iv_md[111:0];
                o_md_wr                <= i_md_wr;    
                if(rv_first_packet_flag[iv_md[128:115]] == 1'b0)begin
                    ov_md[165:156]         <= iv_ram_rdata[9:0];//InjectionSlot.
                end
                else begin
                    ov_md[165:156]         <= iv_ram_rdata[73:64];//InjectionSlot.
                end                   
                if(iv_ram_rdata[63:32] == 32'h0)begin
                    ov_md[199]         <= 1'b1;//discard
                end
                else begin
                    ov_md[199]         <= 1'b0;//not discard
                end
                debug_signal  <= rv_first_packet_flag[iv_md[128:115]];
               ///pjt-0621
               
                if(rv_first_packet_flag[iv_md[128:115]] == 1'b0)begin
                    o_ram_wr      <= 1'b1 ; 
                    ov_ram_waddr  <= iv_md[128:115];//flowid
                    if({1'b0,iv_ram_rdata[9:0]} + {1'b0,iv_ram_rdata[19:10]} <= (iv_inject_period - 1'b1))begin
                        ov_ram_wdata  <= {iv_ram_rdata[9:0] + iv_ram_rdata[19:10],iv_ram_rdata[63:0]};
                    end
                    else begin
                        ov_ram_wdata  <= {iv_ram_rdata[9:0] + iv_ram_rdata[19:10] - iv_inject_period[9:0],iv_ram_rdata[63:0]};
                    end 
                end
                else begin
                    o_ram_wr      <= 1'b1 ; 
                    ov_ram_waddr  <= iv_md[128:115];//flowid
                    if({1'b0,iv_ram_rdata[73:64]} + {1'b0,iv_ram_rdata[19:10]} <= (iv_inject_period - 1'b1))begin
                        ov_ram_wdata  <= {iv_ram_rdata[73:64] + iv_ram_rdata[19:10],iv_ram_rdata[63:0]};
                    end
                    else begin
                        ov_ram_wdata  <= {iv_ram_rdata[73:64] + iv_ram_rdata[19:10] - iv_inject_period[9:0],iv_ram_rdata[63:0]};
                    end                
                end             
            end
        end
        else begin
            o_ram_wr      <= 1'b0 ;
         
            ov_md         <= 300'h0;
            o_md_wr       <= 1'h0;
        end
    end
end

always @(posedge i_clk or negedge i_rst_n) begin
    if(i_rst_n == 1'b0)begin
        rv_first_packet_flag <= 1024'b0;
    end                              
    else begin
        if(i_cyclestart)begin
            if(i_md_wr && (iv_md[111:96] == 16'h8100))begin
                rv_first_packet_flag <=(1024'b1 << iv_md[128:115]);
            end
            else begin
                rv_first_packet_flag <= 1024'b0;
            end
        end
        else begin
            if(i_md_wr && (iv_md[111:96] == 16'h8100))begin
                rv_first_packet_flag[iv_md[128:115]] <= 1'b1;
            end
            else begin
                rv_first_packet_flag <= rv_first_packet_flag;
            end                
        end     
    end
end
endmodule
